home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / sprite.X11R3 / spriteGC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-19  |  38.0 KB  |  1,509 lines

  1. /*-
  2.  * spriteGC.c --
  3.  *    Functions to support the meddling with GC's we do to preserve
  4.  *    the software cursor...
  5.  *
  6.  * Copyright (c) 1987 by the Regents of the University of California
  7.  *
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  *
  16.  *
  17.  */
  18. #ifndef lint
  19. static char rcsid[] =
  20.     "$Header: /mic/X11R3/src/cmds/Xsp/ddx/sprite/RCS/spriteGC.c,v 1.9 89/11/18 20:57:24 tve Exp $ SPRITE (Berkeley)";
  21. #endif lint
  22.  
  23. #include    "spriteddx.h"
  24.  
  25. #include    "Xmd.h"
  26. #include    "extnsionst.h"
  27. #include    "regionstr.h"
  28. #include    "windowstr.h"
  29. #include    "fontstruct.h"
  30. #include    "dixfontstr.h"
  31. #include    "../mi/mifpoly.h"        /* for SppPointPtr */
  32. #ifdef foobarsun4
  33. #include    "alloca.h"
  34. #include    "stdio.h"
  35. #endif
  36.  
  37. /*
  38.  * Overlap BoxPtr and Box elements
  39.  */
  40. #define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
  41.      (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
  42.      ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
  43.  
  44. /*
  45.  * Overlap BoxPtr, origins, and rectangle
  46.  */
  47. #define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
  48.     BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
  49.  
  50. /*
  51.  * Overlap BoxPtr, origins and RectPtr
  52.  */
  53. #define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
  54.     ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y,(pRect)->width, \
  55.         (pRect)->height)
  56. /*
  57.  * Overlap BoxPtr and horizontal span
  58.  */
  59. #define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
  60.  
  61. /*
  62.  * See if should check for cursor overlap. Drawable must be a window,
  63.  * be realized and on the same screen as the cursor. We don't try and do
  64.  * any region checking because it's slow and it leaves mouse droppings when
  65.  * doing a newiconify in uwm and you're moving the grid over a child of
  66.  * the RootWindow...
  67.  */
  68. #define Check(pDraw) \
  69.      ((((DrawablePtr)(pDraw))->type == DRAWABLE_WINDOW) && \
  70.      ((WindowPtr)(pDraw))->viewable && \
  71.      spriteCursorLoc ((((DrawablePtr)(pDraw))->pScreen), &cursorBox))
  72.  
  73. /*-
  74.  *-----------------------------------------------------------------------
  75.  * spriteSaveCursorBox --
  76.  *    Given an array of points, figure out the bounding box for the
  77.  *    series and remove the cursor if it overlaps that box.
  78.  *
  79.  * Results:
  80.  *
  81.  * Side Effects:
  82.  *
  83.  *-----------------------------------------------------------------------
  84.  */
  85. void
  86. spriteSaveCursorBox (xorg, yorg, mode, lw, pPts, nPts, pCursorBox)
  87.     register int          xorg;           /* X-Origin for points */
  88.     register int          yorg;           /* Y-Origin for points */
  89.     int                      mode;           /* CoordModeOrigin or
  90.                          * CoordModePrevious */
  91.     int                lw;            /* line width */
  92.     register DDXPointPtr    pPts;           /* Array of points */
  93.     int                      nPts;           /* Number of points */
  94.     register BoxPtr         pCursorBox;        /* Bounding box for cursor */
  95. {
  96.     register int          minx,           /* Lowest X coordinate of all pts*/
  97.                 miny,           /* Lowest Y coordinate */
  98.                 maxx,           /* Highest X coordinate */
  99.                 maxy;           /* Highest Y coordinate */
  100.  
  101.     minx = maxx = pPts->x + xorg;
  102.     miny = maxy = pPts->y + yorg;
  103.  
  104.     pPts++;
  105.     nPts--;
  106.  
  107.     if (mode == CoordModeOrigin) {
  108.     while (nPts--) {
  109.         minx = min(minx, pPts->x + xorg);
  110.         maxx = max(maxx, pPts->x + xorg);
  111.         miny = min(miny, pPts->y + yorg);
  112.         maxy = max(maxy, pPts->y + yorg);
  113.         pPts++;
  114.     }
  115.     } else {
  116.     xorg = minx;
  117.     yorg = miny;
  118.     while (nPts--) {
  119.         minx = min(minx, pPts->x + xorg);
  120.         maxx = max(maxx, pPts->x + xorg);
  121.         miny = min(miny, pPts->y + yorg);
  122.         maxy = max(maxy, pPts->y + yorg);
  123.         xorg += pPts->x;
  124.         yorg += pPts->y;
  125.         pPts++;
  126.     }
  127.     }
  128.     if (BOX_OVERLAP(pCursorBox,minx-lw,miny-lw,maxx+lw,maxy+lw)) {
  129.     spriteRemoveCursor();
  130.     }
  131. }
  132.                
  133. /*-
  134.  *-----------------------------------------------------------------------
  135.  * spriteFillSpans --
  136.  *    Remove the cursor if any of the spans overlaps the area covered
  137.  *    by the cursor. This assumes the points have been translated
  138.  *    already, though perhaps it shouldn't...
  139.  *
  140.  * Results:
  141.  *    None.
  142.  *
  143.  * Side Effects:
  144.  *
  145.  *-----------------------------------------------------------------------
  146.  */
  147. void
  148. spriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
  149.     DrawablePtr pDrawable;
  150.     GCPtr    pGC;
  151.     int        nInit;            /* number of spans to fill */
  152.     DDXPointPtr pptInit;        /* pointer to list of start points */
  153.     int        *pwidthInit;        /* pointer to list of n widths */
  154.     int     fSorted;
  155. {
  156.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  157.     BoxRec      cursorBox;
  158.  
  159.     if (Check(pDrawable)) {
  160.     register DDXPointPtr    pts;
  161.     register int        *widths;
  162.     register int        nPts;
  163.     
  164.     for (pts = pptInit, widths = pwidthInit, nPts = nInit;
  165.          nPts--;
  166.          pts++, widths++) {
  167.          if (SPN_OVERLAP(&cursorBox,pts->y,pts->x,*widths)) {
  168.              spriteRemoveCursor();
  169.              break;
  170.          }
  171.     }
  172.     }
  173.  
  174.     (* pShadowGC->FillSpans)(pDrawable, pShadowGC, nInit, pptInit,
  175.                  pwidthInit, fSorted);
  176. }
  177.  
  178. /*-
  179.  *-----------------------------------------------------------------------
  180.  * spriteSetSpans --
  181.  *    Remove the cursor if any of the horizontal segments overlaps
  182.  *    the area covered by the cursor. This also assumes the spans
  183.  *    have been translated from the window's coordinates to the
  184.  *    screen's.
  185.  * Results:
  186.  *    None.
  187.  *
  188.  * Side Effects:
  189.  *
  190.  *-----------------------------------------------------------------------
  191.  */
  192. void
  193. spriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
  194.     DrawablePtr        pDrawable;
  195.     GCPtr        pGC;
  196.     int            *psrc;
  197.     register DDXPointPtr ppt;
  198.     int            *pwidth;
  199.     int            nspans;
  200.     int            fSorted;
  201. {
  202.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  203.     BoxRec      cursorBox;
  204.  
  205.     if (Check(pDrawable)) {
  206.     register DDXPointPtr    pts;
  207.     register int        *widths;
  208.     register int        nPts;
  209.     
  210.     for (pts = ppt, widths = pwidth, nPts = nspans;
  211.          nPts--;
  212.          pts++, widths++) {
  213.          if (SPN_OVERLAP(&cursorBox,pts->y,pts->x,*widths)) {
  214.              spriteRemoveCursor();
  215.              break;
  216.          }
  217.     }
  218.     }
  219.  
  220.     (* pShadowGC->SetSpans) (pDrawable, pShadowGC, psrc, ppt, pwidth,
  221.                  nspans, fSorted);
  222. }
  223.  
  224. /*-
  225.  *-----------------------------------------------------------------------
  226.  * spriteGetSpans --
  227.  *    Remove the cursor if any of the desired spans overlaps it.
  228.  *
  229.  * Results:
  230.  *
  231.  * Side Effects:
  232.  *
  233.  *-----------------------------------------------------------------------
  234.  */
  235. unsigned int *
  236. spriteGetSpans(pDrawable, wMax, ppt, pwidth, nspans)
  237.     DrawablePtr        pDrawable;    /* drawable from which to get bits */
  238.     int            wMax;        /* largest value of all *pwidths */
  239.     register DDXPointPtr ppt;        /* points to start copying from */
  240.     int            *pwidth;    /* list of number of bits to copy */
  241.     int            nspans;        /* number of scanlines to copy */
  242. {
  243.     BoxRec      cursorBox;
  244.  
  245.     if (Check(pDrawable)) {
  246.     register DDXPointPtr    pts;
  247.     register int            *widths;
  248.     register int            nPts;
  249.     register int            xorg,
  250.                     yorg;
  251.     
  252.     xorg = ((WindowPtr)pDrawable)->absCorner.x;
  253.     yorg = ((WindowPtr)pDrawable)->absCorner.y;
  254.     
  255.     for (pts = ppt, widths = pwidth, nPts = nspans;
  256.          nPts--;
  257.          pts++, widths++) {
  258.          if (SPN_OVERLAP(&cursorBox,pts->y+yorg,
  259.                  pts->x+xorg,*widths)) {
  260.                      spriteRemoveCursor();
  261.                      break;
  262.          }
  263.     }
  264.     }
  265.  
  266.     /*
  267.      * XXX: Because we have no way to get at the GC used to call us,
  268.      * we must rely on the GetSpans vector never changing and stick it
  269.      * in the fbFd structure. Gross.
  270.      */
  271.     return (* spriteFbs[pDrawable->pScreen->myNum].GetSpans)(pDrawable, wMax,
  272.                               ppt, pwidth, nspans);
  273. }
  274.  
  275. /*-
  276.  *-----------------------------------------------------------------------
  277.  * spritePutImage --
  278.  *    Remove the cursor if it is in the way of the image to be
  279.  *    put down...
  280.  *
  281.  * Results:
  282.  *    None.
  283.  *
  284.  * Side Effects:
  285.  *
  286.  *-----------------------------------------------------------------------
  287.  */
  288. void
  289. spritePutImage(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits)
  290.     DrawablePtr      pDst;
  291.     GCPtr         pGC;
  292.     int          depth;
  293.     int              x;
  294.     int              y;
  295.     int              w;
  296.     int              h;
  297.     int              format;
  298.     char          *pBits;
  299. {
  300.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  301.     BoxRec      cursorBox;
  302.  
  303.     if (Check(pDst)) {
  304.     register WindowPtr pWin = (WindowPtr)pDst;
  305.  
  306.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  307.             x,y,w,h)) {
  308.                 spriteRemoveCursor();
  309.     }
  310.     }
  311.  
  312.     (* pShadowGC->PutImage) (pDst, pShadowGC, depth, x, y, w, h,
  313.                  leftPad, format, pBits);
  314. }
  315.  
  316. /*-
  317.  *-----------------------------------------------------------------------
  318.  * spriteGetImage --
  319.  *    Remove the cursor if it overlaps the image to be gotten.
  320.  *
  321.  * Results:
  322.  *    None.
  323.  *
  324.  * Side Effects:
  325.  *
  326.  *-----------------------------------------------------------------------
  327.  */
  328. void
  329. spriteGetImage (pSrc, x, y, w, h, format, planeMask, pBits)
  330.     DrawablePtr      pSrc;
  331.     int              x;
  332.     int              y;
  333.     int              w;
  334.     int              h;
  335.     unsigned int  format;
  336.     unsigned int  planeMask;
  337.     int              *pBits;
  338. {
  339.     BoxRec      cursorBox;
  340.     if (Check(pSrc)) {
  341.     register WindowPtr    pWin = (WindowPtr)pSrc;
  342.     
  343.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  344.             x,y,w,h)) {
  345.                 spriteRemoveCursor();
  346.     }
  347.     }
  348.  
  349.     (* spriteFbs[pSrc->pScreen->myNum].GetImage) (pSrc, x, y, w, h, format,
  350.                            planeMask, pBits);
  351. }
  352.  
  353. /*-
  354.  *-----------------------------------------------------------------------
  355.  * spriteCopyArea --
  356.  *    Remove the cursor if it overlaps either the source or destination
  357.  *    drawables, then call the screen-specific CopyArea routine.
  358.  *
  359.  * Results:
  360.  *    None.
  361.  *
  362.  * Side Effects:
  363.  *
  364.  *-----------------------------------------------------------------------
  365.  */
  366. RegionPtr
  367. spriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
  368.     DrawablePtr      pSrc;
  369.     DrawablePtr      pDst;
  370.     GCPtr         pGC;
  371.     int              srcx;
  372.     int              srcy;
  373.     int              w;
  374.     int              h;
  375.     int              dstx;
  376.     int              dsty;
  377. {
  378.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  379.     BoxRec      cursorBox;
  380.     register WindowPtr    pWin;
  381.     int              out = FALSE;
  382.  
  383.     if (Check(pSrc)) {
  384.     pWin = (WindowPtr)pSrc;
  385.  
  386.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  387.             srcx, srcy, w, h)) {
  388.                 spriteRemoveCursor();
  389.                 out = TRUE;
  390.     }
  391.     }
  392.  
  393.     if (!out && Check(pDst)) {
  394.     pWin = (WindowPtr)pDst;
  395.         
  396.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  397.             dstx, dsty, w, h)) {
  398.                 spriteRemoveCursor();
  399.     }
  400.     }
  401.  
  402.     return (* pShadowGC->CopyArea) (pSrc, pDst, pShadowGC, srcx, srcy,
  403.                  w, h, dstx, dsty);
  404. }
  405.  
  406. /*-
  407.  *-----------------------------------------------------------------------
  408.  * spriteCopyPlane --
  409.  *    Remove the cursor as necessary and call the screen-specific
  410.  *    CopyPlane function.
  411.  *
  412.  * Results:
  413.  *    None.
  414.  *
  415.  * Side Effects:
  416.  *
  417.  *-----------------------------------------------------------------------
  418.  */
  419. RegionPtr
  420. spriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
  421.     DrawablePtr      pSrc;
  422.     DrawablePtr      pDst;
  423.     register GC   *pGC;
  424.     int           srcx,
  425.           srcy;
  426.     int           w,
  427.           h;
  428.     int           dstx,
  429.           dsty;
  430.     unsigned int  plane;
  431. {
  432.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  433.     BoxRec      cursorBox;
  434.     register WindowPtr    pWin;
  435.     int              out = FALSE;
  436.  
  437.     if (Check(pSrc)){
  438.     pWin = (WindowPtr)pSrc;
  439.  
  440.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  441.             srcx, srcy, w, h)) {
  442.                 spriteRemoveCursor();
  443.                 out = TRUE;
  444.     }
  445.     }
  446.  
  447.     if (!out && Check(pDst)) {
  448.     pWin = (WindowPtr)pDst;
  449.     
  450.     if (ORG_OVERLAP(&cursorBox,pWin->absCorner.x,pWin->absCorner.y,
  451.             dstx, dsty, w, h)) {
  452.                 spriteRemoveCursor();
  453.     }
  454.     }
  455.  
  456.  
  457.     return (* pShadowGC->CopyPlane) (pSrc, pDst, pShadowGC, srcx, srcy, w, h,
  458.                   dstx, dsty, plane);
  459. }
  460.  
  461. /*-
  462.  *-----------------------------------------------------------------------
  463.  * spritePolyPoint --
  464.  *    See if any of the points lies within the area covered by the
  465.  *    cursor and remove the cursor if one does. Then put the points
  466.  *    down.
  467.  *
  468.  * Results:
  469.  *    None.
  470.  *
  471.  * Side Effects:
  472.  *
  473.  *-----------------------------------------------------------------------
  474.  */
  475. void
  476. spritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
  477.     DrawablePtr pDrawable;
  478.     GCPtr    pGC;
  479.     int        mode;        /* Origin or Previous */
  480.     int        npt;
  481.     xPoint     *pptInit;
  482. {
  483.     register GCPtr     pShadowGC = (GCPtr) pGC->devPriv;
  484.     register xPoint     *pts;
  485.     register int      nPts;
  486.     register int      xorg;
  487.     register int      yorg;
  488.     BoxRec            cursorBox;
  489.  
  490.     if (Check(pDrawable)){
  491.     xorg = ((WindowPtr)pDrawable)->absCorner.x;
  492.     yorg = ((WindowPtr)pDrawable)->absCorner.y;
  493.     
  494.     if (mode == CoordModeOrigin) {
  495.         for (pts = pptInit, nPts = npt; nPts--; pts++) {
  496.         if (ORG_OVERLAP(&cursorBox,xorg,yorg,pts->x,pts->y,0,0)){
  497.             spriteRemoveCursor();
  498.             break;
  499.         }
  500.         }
  501.     } else {
  502.         for (pts = pptInit, nPts = npt; nPts--; pts++) {
  503.         if (ORG_OVERLAP(&cursorBox,xorg,yorg,pts->x,pts->y,0,0)){
  504.             spriteRemoveCursor();
  505.             break;
  506.         } else {
  507.             xorg += pts->x;
  508.             yorg += pts->y;
  509.         }
  510.         }
  511.     }
  512.     }
  513.  
  514.     (* pShadowGC->PolyPoint) (pDrawable, pShadowGC, mode, npt, pptInit);
  515. }
  516.  
  517. /*-
  518.  *-----------------------------------------------------------------------
  519.  * spritePolylines --
  520.  *    Find the bounding box of the lines and remove the cursor if
  521.  *    the box overlaps the area covered by the cursor. Then call
  522.  *    the screen's Polylines function to draw the lines themselves.
  523.  *
  524.  * Results:
  525.  *
  526.  * Side Effects:
  527.  *
  528.  *-----------------------------------------------------------------------
  529.  */
  530. void
  531. spritePolylines (pDrawable, pGC, mode, npt, pptInit)
  532.     DrawablePtr      pDrawable;
  533.     GCPtr         pGC;
  534.     int              mode;
  535.     int              npt;
  536.     DDXPointPtr      pptInit;
  537. {
  538.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  539.     BoxRec        cursorBox;
  540.  
  541.     if (Check(pDrawable)){
  542.     spriteSaveCursorBox(((WindowPtr)pDrawable)->absCorner.x,
  543.                 ((WindowPtr)pDrawable)->absCorner.y,
  544.                 mode,
  545.                 pShadowGC->lineWidth,
  546.                 pptInit,
  547.                 npt,
  548.                 &cursorBox);
  549.     }
  550.     (*pShadowGC->Polylines) (pDrawable, pShadowGC, mode, npt, pptInit);
  551. }
  552.  
  553. /*-
  554.  *-----------------------------------------------------------------------
  555.  * spritePolySegment --
  556.  *    Treat each segment as a box and remove the cursor if any box
  557.  *    overlaps the cursor's area. Then draw the segments. Note that
  558.  *    the endpoints of the segments are in no way guaranteed to be
  559.  *    in the right order, so we find the bounding box of the segment
  560.  *    in two comparisons and use that to figure things out.
  561.  *
  562.  * Results:
  563.  *    None.
  564.  *
  565.  * Side Effects:
  566.  *
  567.  *-----------------------------------------------------------------------
  568.  */
  569. void
  570. spritePolySegment(pDraw, pGC, nseg, pSegs)
  571.     DrawablePtr pDraw;
  572.     GCPtr     pGC;
  573.     int        nseg;
  574.     xSegment    *pSegs;
  575. {
  576.     register GCPtr     pShadowGC = (GCPtr) pGC->devPriv;
  577.     register xSegment    *pSeg;
  578.     register int      nSeg;
  579.     register int      xorg,
  580.             yorg;
  581.     BoxRec            cursorBox;
  582.     Bool              nuke = FALSE;
  583.  
  584.     if (Check(pDraw)){
  585.     xorg = ((WindowPtr)pDraw)->absCorner.x;
  586.     yorg = ((WindowPtr)pDraw)->absCorner.y;
  587.     
  588.     for (nSeg = nseg, pSeg = pSegs; nSeg--; pSeg++) {
  589.         if (pSeg->x1 < pSeg->x2) {
  590.         if (pSeg->y1 < pSeg->y2) {
  591.             nuke = BOX_OVERLAP(&cursorBox,
  592.                        pSeg->x1+xorg,pSeg->y1+yorg,
  593.                        pSeg->x2+xorg,pSeg->y2+yorg);
  594.         } else {
  595.             nuke = BOX_OVERLAP(&cursorBox,
  596.                        pSeg->x1+xorg,pSeg->y2+yorg,
  597.                        pSeg->x2+xorg,pSeg->y1+yorg);
  598.         }
  599.         } else if (pSeg->y1 < pSeg->y2) {
  600.         nuke = BOX_OVERLAP(&cursorBox,
  601.                    pSeg->x2+xorg,pSeg->y1+yorg,
  602.                    pSeg->x1+xorg,pSeg->y2+yorg);
  603.         } else {
  604.         nuke = BOX_OVERLAP(&cursorBox,
  605.                    pSeg->x2+xorg,pSeg->y2+yorg,
  606.                    pSeg->x1+xorg,pSeg->y1+yorg);
  607.         }
  608.         if (nuke) {
  609.         spriteRemoveCursor();
  610.         break;
  611.         }
  612.     }
  613.     }
  614.  
  615.     (* pShadowGC->PolySegment) (pDraw, pShadowGC, nseg, pSegs);
  616. }
  617.  
  618. /*-
  619.  *-----------------------------------------------------------------------
  620.  * spritePolyRectangle --
  621.  *    Remove the cursor if it overlaps any of the rectangles to be
  622.  *    drawn, then draw them.
  623.  *
  624.  * Results:
  625.  *    None
  626.  *
  627.  * Side Effects:
  628.  *
  629.  *-----------------------------------------------------------------------
  630.  */
  631. void
  632. spritePolyRectangle(pDraw, pGC, nrects, pRects)
  633.     DrawablePtr    pDraw;
  634.     GCPtr    pGC;
  635.     int        nrects;
  636.     xRectangle    *pRects;
  637. {
  638.     register GCPtr     pShadowGC = (GCPtr) pGC->devPriv;
  639.     register xRectangle    *pRect;
  640.     register int      nRect;
  641.     register int      xorg,
  642.             yorg;
  643.     BoxRec            cursorBox;
  644.  
  645.     if (Check(pDraw)) {
  646.     xorg = ((WindowPtr)pDraw)->absCorner.x;
  647.     yorg = ((WindowPtr)pDraw)->absCorner.y;
  648.     
  649.     for (nRect = nrects, pRect = pRects; nRect--; pRect++) {
  650.         if (ORGRECT_OVERLAP(&cursorBox,xorg,yorg,pRect)){
  651.         spriteRemoveCursor();
  652.         break;
  653.         }
  654.     }
  655.     }
  656.  
  657.     (* pShadowGC->PolyRectangle) (pDraw, pShadowGC, nrects, pRects);
  658. }
  659.  
  660. /*-
  661.  *-----------------------------------------------------------------------
  662.  * spritePolyArc --
  663.  *    Using the bounding rectangle of each arc, remove the cursor
  664.  *    if it overlaps any arc, then draw all the arcs.
  665.  *
  666.  * Results:
  667.  *
  668.  * Side Effects:
  669.  *
  670.  *-----------------------------------------------------------------------
  671.  */
  672. void
  673. spritePolyArc(pDraw, pGC, narcs, parcs)
  674.     DrawablePtr    pDraw;
  675.     GCPtr    pGC;
  676.     int        narcs;
  677.     xArc    *parcs;
  678. {
  679.     register GCPtr     pShadowGC = (GCPtr) pGC->devPriv;
  680.     register xArc    *pArc;
  681.     register int      nArc;
  682.     register int      xorg,
  683.             yorg;
  684.     BoxRec            cursorBox;
  685.  
  686.     if (Check(pDraw)) {
  687.     xorg = ((WindowPtr)pDraw)->absCorner.x;
  688.     yorg = ((WindowPtr)pDraw)->absCorner.y;
  689.     
  690.     for (nArc = narcs, pArc = parcs; nArc--; pArc++) {
  691.         if (ORGRECT_OVERLAP(&cursorBox,xorg,yorg,pArc)){
  692.         spriteRemoveCursor();
  693.         break;
  694.         }
  695.     }
  696.     }
  697.  
  698.     (* pShadowGC->PolyArc) (pDraw, pShadowGC, narcs, parcs);
  699. }
  700.  
  701. /*-
  702.  *-----------------------------------------------------------------------
  703.  * spriteFillPolygon --
  704.  *    Find the bounding box of the polygon to fill and remove the
  705.  *    cursor if it overlaps this box...
  706.  *
  707.  * Results:
  708.  *    None.
  709.  *
  710.  * Side Effects:
  711.  *
  712.  *-----------------------------------------------------------------------
  713.  */
  714. void
  715. spriteFillPolygon(pDraw, pGC, shape, mode, count, pPts)
  716.     DrawablePtr        pDraw;
  717.     register GCPtr    pGC;
  718.     int            shape, mode;
  719.     register int    count;
  720.     DDXPointPtr        pPts;
  721. {
  722.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  723.     BoxRec            cursorBox;
  724.  
  725.     if (Check(pDraw)) {
  726.     spriteSaveCursorBox(((WindowPtr)pDraw)->absCorner.x,
  727.                 ((WindowPtr)pDraw)->absCorner.y,
  728.                 mode,
  729.                 0,
  730.                 pPts,
  731.                 count,
  732.                 &cursorBox);
  733.     }
  734.  
  735.     (* pShadowGC->FillPolygon) (pDraw, pShadowGC, shape, mode, count, pPts);
  736. }
  737.  
  738. /*-
  739.  *-----------------------------------------------------------------------
  740.  * spritePolyFillRect --
  741.  *    Remove the cursor if it overlaps any of the filled rectangles
  742.  *    to be drawn by the output routines.
  743.  *
  744.  * Results:
  745.  *    None.
  746.  *
  747.  * Side Effects:
  748.  *
  749.  *-----------------------------------------------------------------------
  750.  */
  751. void
  752. spritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
  753.     DrawablePtr pDrawable;
  754.     GCPtr    pGC;
  755.     int        nrectFill;     /* number of rectangles to fill */
  756.     xRectangle    *prectInit;      /* Pointer to first rectangle to fill */
  757. {
  758.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  759.     register xRectangle    *pRect;
  760.     register int      nRect;
  761.     register int      xorg,
  762.             yorg;
  763.     BoxRec            cursorBox;
  764.  
  765.     if (Check(pDrawable)) {
  766.     xorg = ((WindowPtr)pDrawable)->absCorner.x;
  767.     yorg = ((WindowPtr)pDrawable)->absCorner.y;
  768.     
  769.     for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
  770.         if (ORGRECT_OVERLAP(&cursorBox,xorg,yorg,pRect)){
  771.         spriteRemoveCursor();
  772.         break;
  773.         }
  774.     }
  775.     }
  776.  
  777.     (* pShadowGC->PolyFillRect) (pDrawable, pShadowGC, nrectFill, prectInit);
  778. }
  779.  
  780. /*-
  781.  *-----------------------------------------------------------------------
  782.  * spritePolyFillArc --
  783.  *    See if the cursor overlaps any of the bounding boxes for the
  784.  *    filled arc and remove it if it does.
  785.  *
  786.  * Results:
  787.  *    None.
  788.  *
  789.  * Side Effects:
  790.  *
  791.  *-----------------------------------------------------------------------
  792.  */
  793. void
  794. spritePolyFillArc(pDraw, pGC, narcs, parcs)
  795.     DrawablePtr    pDraw;
  796.     GCPtr    pGC;
  797.     int        narcs;
  798.     xArc    *parcs;
  799. {
  800.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  801.     register xArc    *pArc;
  802.     register int      nArc;
  803.     register int      xorg,
  804.             yorg;
  805.     BoxRec            cursorBox;
  806.  
  807.     if (Check(pDraw)) {
  808.     xorg = ((WindowPtr)pDraw)->absCorner.x;
  809.     yorg = ((WindowPtr)pDraw)->absCorner.y;
  810.     
  811.     for (nArc = narcs, pArc = parcs; nArc--; pArc++) {
  812.         if (ORGRECT_OVERLAP(&cursorBox,xorg,yorg,pArc)){
  813.         spriteRemoveCursor();
  814.         break;
  815.         }
  816.     }
  817.     }
  818.  
  819.     (* pShadowGC->PolyFillArc) (pDraw, pShadowGC, narcs, parcs);
  820. }
  821.  
  822. /*-
  823.  *-----------------------------------------------------------------------
  824.  * spriteText --
  825.  *    Find the extent of a text operation and remove the cursor if they
  826.  *    overlap. pDraw is assumed to be a window.
  827.  *
  828.  * Results:
  829.  *
  830.  * Side Effects:
  831.  *
  832.  *-----------------------------------------------------------------------
  833.  */
  834. int
  835. spriteText(pDraw, pGC, x, y, count, chars, fontEncoding, drawFunc)
  836.     DrawablePtr   pDraw;
  837.     GCPtr      pGC;
  838.     int          x,
  839.           y;
  840.     int          count;
  841.     char       *chars;
  842.     FontEncoding  fontEncoding;
  843.     void          (*drawFunc)();
  844. {
  845.     CharInfoPtr   *charinfo;
  846.     unsigned int  n,
  847.           w;
  848.     register int  xorg,
  849.           yorg;
  850.     ExtentInfoRec extents;
  851.     BoxRec        cursorBox;
  852.  
  853.     charinfo = (CharInfoPtr *)ALLOCATE_LOCAL (count * sizeof(CharInfoPtr));
  854.     if (charinfo == (CharInfoPtr *)NULL) {
  855.     return x;
  856.     }
  857.  
  858.     GetGlyphs(pGC->font, count, chars, fontEncoding, &n, charinfo);
  859.  
  860.     if (n != 0) {
  861.     /*
  862.      * Because we need to know the width of the operation in order to
  863.      * return the new offset, we always have to do this. Let's hope
  864.      * QueryGlyphExtents has been optimized...
  865.      */
  866.     QueryGlyphExtents(pGC->font, charinfo, n, &extents);
  867.     w = extents.overallWidth;
  868.     if (spriteCursorLoc (pDraw->pScreen, &cursorBox)) {
  869.         xorg = ((WindowPtr)pDraw)->absCorner.x;
  870.         yorg = ((WindowPtr)pDraw)->absCorner.y;
  871.     
  872.         if (BOX_OVERLAP(&cursorBox,
  873.                 x + xorg + extents.overallLeft,
  874.                 y + yorg - extents.overallAscent,
  875.                 x + xorg + extents.overallRight,
  876.                 y + yorg + extents.overallDescent)) {
  877.                 spriteRemoveCursor();
  878.         }
  879.     }
  880.         (* drawFunc)(pDraw, pGC, x, y, n, charinfo, pGC->font->pGlyphs);
  881.     } else {
  882.     w = 0;
  883.     }
  884.     
  885.     DEALLOCATE_LOCAL(charinfo);
  886.     return x+w;
  887. }
  888.  
  889. /*-
  890.  *-----------------------------------------------------------------------
  891.  * spritePolyText8 --
  892.  *
  893.  * Results:
  894.  *
  895.  * Side Effects:
  896.  *
  897.  *-----------------------------------------------------------------------
  898.  */
  899. int
  900. spritePolyText8(pDraw, pGC, x, y, count, chars)
  901.     DrawablePtr pDraw;
  902.     GCPtr    pGC;
  903.     int        x, y;
  904.     int     count;
  905.     char    *chars;
  906. {
  907.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  908.  
  909.     if ((pDraw->type == DRAWABLE_WINDOW) && ((WindowPtr)pDraw)->viewable) {
  910.     return spriteText (pDraw, pShadowGC, x, y, count, chars, Linear8Bit,
  911.             pShadowGC->PolyGlyphBlt);
  912.     } else {
  913.     return (* pShadowGC->PolyText8)(pDraw, pShadowGC, x, y, count, chars);
  914.     }
  915. }
  916.  
  917. /*-
  918.  *-----------------------------------------------------------------------
  919.  * spritePolyText16 --
  920.  *
  921.  * Results:
  922.  *
  923.  * Side Effects:
  924.  *
  925.  *-----------------------------------------------------------------------
  926.  */
  927. int
  928. spritePolyText16(pDraw, pGC, x, y, count, chars)
  929.     DrawablePtr pDraw;
  930.     GCPtr    pGC;
  931.     int        x, y;
  932.     int        count;
  933.     unsigned short *chars;
  934. {
  935.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  936.  
  937.     if ((pDraw->type == DRAWABLE_WINDOW) && ((WindowPtr)pDraw)->viewable) {
  938.     return spriteText (pDraw, pShadowGC, x, y, count, chars,
  939.             (pShadowGC->font->pFI->lastRow == 0 ?
  940.              Linear16Bit : TwoD16Bit),
  941.             pShadowGC->PolyGlyphBlt);
  942.     } else {
  943.     return (* pShadowGC->PolyText16) (pDraw, pShadowGC, x, y,
  944.                       count, chars);
  945.     }
  946. }
  947.  
  948. /*-
  949.  *-----------------------------------------------------------------------
  950.  * spriteImageText8 --
  951.  *
  952.  * Results:
  953.  *
  954.  * Side Effects:
  955.  *
  956.  *-----------------------------------------------------------------------
  957.  */
  958. void
  959. spriteImageText8(pDraw, pGC, x, y, count, chars)
  960.     DrawablePtr pDraw;
  961.     GCPtr    pGC;
  962.     int        x, y;
  963.     int        count;
  964.     char    *chars;
  965. {
  966.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  967.  
  968.     if ((pDraw->type == DRAWABLE_WINDOW) && ((WindowPtr)pDraw)->viewable) {
  969.     (void) spriteText (pDraw, pShadowGC, x, y, count, chars,
  970.             Linear8Bit, pShadowGC->ImageGlyphBlt);
  971.     } else {
  972.     (* pShadowGC->ImageText8) (pDraw, pShadowGC, x, y, count, chars);
  973.     }
  974. }
  975.  
  976. /*-
  977.  *-----------------------------------------------------------------------
  978.  * spriteImageText16 --
  979.  *
  980.  * Results:
  981.  *
  982.  * Side Effects:
  983.  *
  984.  *-----------------------------------------------------------------------
  985.  */
  986. void
  987. spriteImageText16(pDraw, pGC, x, y, count, chars)
  988.     DrawablePtr pDraw;
  989.     GCPtr    pGC;
  990.     int        x, y;
  991.     int        count;
  992.     unsigned short *chars;
  993. {
  994.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  995.  
  996.     if ((pDraw->type == DRAWABLE_WINDOW) && ((WindowPtr)pDraw)->viewable) {
  997.     (void) spriteText (pDraw, pShadowGC, x, y, count, chars,
  998.                (pShadowGC->font->pFI->lastRow == 0 ?
  999.                 Linear16Bit : TwoD16Bit),
  1000.                pShadowGC->ImageGlyphBlt);
  1001.     } else {
  1002.     (* pShadowGC->ImageText16) (pDraw, pShadowGC, x, y, count, chars);
  1003.     }
  1004. }
  1005.  
  1006. /*-
  1007.  *-----------------------------------------------------------------------
  1008.  * spriteImageGlyphBlt --
  1009.  *
  1010.  * Results:
  1011.  *
  1012.  * Side Effects:
  1013.  *
  1014.  *-----------------------------------------------------------------------
  1015.  */
  1016. void
  1017. spriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1018.     DrawablePtr pDrawable;
  1019.     GC         *pGC;
  1020.     int     x, y;
  1021.     unsigned int nglyph;
  1022.     CharInfoPtr *ppci;        /* array of character info */
  1023.     pointer     pglyphBase;    /* start of array of glyphs */
  1024. {
  1025.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  1026.     BoxRec            cursorBox;
  1027.     ExtentInfoRec     extents;
  1028.     register int      xorg,
  1029.             yorg;
  1030.  
  1031.     if (Check(pDrawable)) {
  1032.     QueryGlyphExtents (pGC->font, ppci, nglyph, &extents);
  1033.     xorg = ((WindowPtr)pDrawable)->absCorner.x + x;
  1034.     yorg = ((WindowPtr)pDrawable)->absCorner.y + y;
  1035.     if (BOX_OVERLAP(&cursorBox,xorg+extents.overallLeft,
  1036.             yorg+extents.overallAscent,
  1037.             xorg+extents.overallRight,
  1038.             yorg+extents.overallDescent)) {
  1039.                 spriteRemoveCursor();
  1040.     }
  1041.     }
  1042.  
  1043.     (* pShadowGC->ImageGlyphBlt) (pDrawable, pShadowGC, x, y, nglyph,
  1044.                   ppci, pglyphBase);
  1045. }
  1046.  
  1047. /*-
  1048.  *-----------------------------------------------------------------------
  1049.  * spritePolyGlyphBlt --
  1050.  *
  1051.  * Results:
  1052.  *
  1053.  * Side Effects:
  1054.  *
  1055.  *-----------------------------------------------------------------------
  1056.  */
  1057. void
  1058. spritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1059.     DrawablePtr pDrawable;
  1060.     GCPtr    pGC;
  1061.     int     x, y;
  1062.     unsigned int nglyph;
  1063.     CharInfoPtr *ppci;        /* array of character info */
  1064.     char     *pglyphBase;    /* start of array of glyphs */
  1065. {
  1066.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  1067.     BoxRec            cursorBox;
  1068.     ExtentInfoRec     extents;
  1069.     register int      xorg,
  1070.             yorg;
  1071.  
  1072.     if (Check(pDrawable)) {
  1073.     QueryGlyphExtents (pGC->font, ppci, nglyph, &extents);
  1074.     xorg = ((WindowPtr)pDrawable)->absCorner.x + x;
  1075.     yorg = ((WindowPtr)pDrawable)->absCorner.y + y;
  1076.     if (BOX_OVERLAP(&cursorBox,xorg+extents.overallLeft,
  1077.             yorg+extents.overallAscent,
  1078.             xorg+extents.overallRight,
  1079.             yorg+extents.overallDescent)){
  1080.                 spriteRemoveCursor();
  1081.     }
  1082.     }
  1083.  
  1084.     (* pShadowGC->PolyGlyphBlt) (pDrawable, pShadowGC, x, y,
  1085.                 nglyph, ppci, pglyphBase);
  1086. }
  1087.  
  1088. /*-
  1089.  *-----------------------------------------------------------------------
  1090.  * spritePushPixels --
  1091.  *
  1092.  * Results:
  1093.  *
  1094.  * Side Effects:
  1095.  *
  1096.  *-----------------------------------------------------------------------
  1097.  */
  1098. void
  1099. spritePushPixels(pGC, pBitMap, pDst, w, h, x, y)
  1100.     GCPtr    pGC;
  1101.     PixmapPtr    pBitMap;
  1102.     DrawablePtr pDst;
  1103.     int        w, h, x, y;
  1104. {
  1105.  
  1106.     register GCPtr    pShadowGC = (GCPtr) pGC->devPriv;
  1107.     BoxRec            cursorBox;
  1108.     register int      xorg,
  1109.             yorg;
  1110.  
  1111.     if (Check(pDst)) {
  1112.     xorg = ((WindowPtr)pDst)->absCorner.x + x;
  1113.     yorg = ((WindowPtr)pDst)->absCorner.y + y;
  1114.     
  1115.     if (BOX_OVERLAP(&cursorBox,xorg,yorg,xorg+w,yorg+h)){
  1116.         spriteRemoveCursor();
  1117.     }
  1118.     }
  1119.  
  1120.     (* pShadowGC->PushPixels) (pShadowGC, pBitMap, pDst, w, h, x, y);
  1121. }
  1122.  
  1123. /*-
  1124.  *-----------------------------------------------------------------------
  1125.  * spriteLineHelper --
  1126.  *
  1127.  * Results:
  1128.  *
  1129.  * Side Effects:
  1130.  *
  1131.  *-----------------------------------------------------------------------
  1132.  */
  1133. void
  1134. spriteLineHelper (pDraw, pGC, caps, npt, pPts, xOrg, yOrg)
  1135.     DrawablePtr pDraw;
  1136.     GCPtr    pGC;
  1137.     int        caps;
  1138.     int        npt;
  1139.     SppPointPtr pPts;
  1140.     int        xOrg, yOrg;
  1141. {
  1142.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  1143.  
  1144.     (* pShadowGC->LineHelper) (pDraw, pGC, caps, npt, pPts, xOrg, yOrg);
  1145. }
  1146.  
  1147. /*-
  1148.  *-----------------------------------------------------------------------
  1149.  * spriteChangeClip --
  1150.  *    Front end for changing the clip in the GC. Just passes the command
  1151.  *    on through the shadow GC.
  1152.  *
  1153.  * Results:
  1154.  *    None.
  1155.  *
  1156.  * Side Effects:
  1157.  *    ???
  1158.  *
  1159.  *-----------------------------------------------------------------------
  1160.  */
  1161. void
  1162. spriteChangeClip (pGC, type, pValue, numRects)
  1163.     GCPtr         pGC;
  1164.     int              type;
  1165.     pointer       pValue;
  1166.     int              numRects;
  1167. {
  1168.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  1169.  
  1170.     (* pShadowGC->ChangeClip) (pShadowGC, type, pValue, numRects);
  1171.     /*
  1172.      *    Now copy the clip info back from the shadow to the real
  1173.      *    GC so that if we use it as the source for a CopyGC,
  1174.      *    the clip info will get copied along with everything
  1175.      *    else.
  1176.      */
  1177.     pGC->clientClip = pShadowGC->clientClip;
  1178.     pGC->clientClipType = pShadowGC->clientClipType;
  1179. }
  1180.  
  1181. /*-
  1182.  *-----------------------------------------------------------------------
  1183.  * spriteDestroyClip --
  1184.  *    Ditto for destroying the clipping region of the GC.
  1185.  *
  1186.  * Results:
  1187.  *    None.
  1188.  *
  1189.  * Side Effects:
  1190.  *    ???
  1191.  *
  1192.  *-----------------------------------------------------------------------
  1193.  */
  1194. void
  1195. spriteDestroyClip (pGC)
  1196.     GCPtr   pGC;
  1197. {
  1198.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  1199.  
  1200.     (* pShadowGC->DestroyClip) (pShadowGC);
  1201.     /* presumably this is NULL,  or junk,  or something.... */
  1202.     pGC->clientClip = pShadowGC->clientClip;
  1203.     pGC->clientClipType = pShadowGC->clientClipType;
  1204.  
  1205. }
  1206.  
  1207. /*-
  1208.  *-----------------------------------------------------------------------
  1209.  * spriteCopyClip --
  1210.  *    Ditto for copying the clipping region of the GC. Note that it
  1211.  *    is possible for us to be called to copy the clip from a shadow
  1212.  *    GC to a top-level (one of our) GC (the backing-store scheme in
  1213.  *    MI will do such a thing), so we must be careful.
  1214.  *
  1215.  * Results:
  1216.  *    None.
  1217.  *
  1218.  * Side Effects:
  1219.  *    ???
  1220.  *
  1221.  *-----------------------------------------------------------------------
  1222.  */
  1223. void
  1224. spriteCopyClip (pgcDst, pgcSrc)
  1225.     GCPtr   pgcDst, pgcSrc;
  1226. {
  1227.     register GCPtr pShadowSrcGC = (GCPtr) pgcSrc->devPriv;
  1228.     register GCPtr pShadowDstGC = (GCPtr) pgcDst->devPriv;
  1229.  
  1230.     if ((void (*)())pgcSrc->FillSpans != (void (*)())spriteFillSpans) {
  1231.     /*
  1232.      * The source is a shadow GC in its own right, so don't try to
  1233.      * reference through the devPriv field...
  1234.      */
  1235.     pShadowSrcGC = pgcSrc;
  1236.     }
  1237.     
  1238.     (* pShadowDstGC->CopyClip) (pShadowDstGC, pShadowSrcGC);
  1239.     pgcDst->clientClip = pShadowDstGC->clientClip;
  1240.     pgcDst->clientClipType = pShadowDstGC->clientClipType;
  1241. }
  1242.  
  1243. /*-
  1244.  *-----------------------------------------------------------------------
  1245.  * spriteDestroyGC --
  1246.  *    Function called when a GC is being freed. Simply unlinks and frees
  1247.  *    the GCInterest structure.
  1248.  *
  1249.  * Results:
  1250.  *    None.
  1251.  *
  1252.  * Side Effects:
  1253.  *    The GCInterest structure is removed from the chain but its own
  1254.  *    links are untouched (so FreeGC has something to follow...)
  1255.  *
  1256.  *-----------------------------------------------------------------------
  1257.  */
  1258. void
  1259. spriteDestroyGC (pGC, pGCI)
  1260.     GCPtr       pGC;    /* GC pGCI is attached to */
  1261.     GCInterestPtr  pGCI;    /* GCInterest being destroyed */
  1262. {
  1263.     if (pGC->devPriv)
  1264.     FreeGC ((GCPtr)pGC->devPriv);
  1265.     Xfree (pGCI);
  1266. }
  1267.  
  1268. /*-
  1269.  *-----------------------------------------------------------------------
  1270.  * spriteValidateGC --
  1271.  *    Called when a GC is about to be used for drawing. Copies all
  1272.  *    changes from the GC to its shadow and validates the shadow.
  1273.  *
  1274.  * Results:
  1275.  *    TRUE, for no readily apparent reason.
  1276.  *
  1277.  * Side Effects:
  1278.  *    Vectors in the shadow GC will likely be changed.
  1279.  *
  1280.  *-----------------------------------------------------------------------
  1281.  */
  1282. /*ARGSUSED*/
  1283. static void
  1284. spriteValidateGC (pGC, pGCI, changes, pDrawable)
  1285.     GCPtr      pGC;
  1286.     GCInterestPtr pGCI;
  1287.     Mask      changes;
  1288.     DrawablePtr      pDrawable;
  1289. {
  1290.     register GCPtr pShadowGC = (GCPtr) pGC->devPriv;
  1291.  
  1292.     if ( pGC->depth != pDrawable->depth )
  1293.     FatalError( "spriteValidateGC: depth mismatch.\n" );
  1294. /*
  1295.  *  spriteValidateGC copies the GC to the shadow.  Alas,
  1296.  *  spriteChangeClip has stored the new clip in the shadow,
  1297.  *  where it will be overwritten,  unless we pretend
  1298.  *  that the clip hasn't changed.
  1299.  */
  1300.     changes &= ~GCClipMask;
  1301.  
  1302.     CopyGC (pGC, pShadowGC, changes);
  1303.     pShadowGC->serialNumber = pGC->serialNumber;
  1304.     ValidateGC (pDrawable, pShadowGC);
  1305. }
  1306.     
  1307. /*-
  1308.  *-----------------------------------------------------------------------
  1309.  * spriteCopyGC --
  1310.  *    Called when a GC with its shadow is the destination of a copy.
  1311.  *    Calls CopyGC to transfer the changes to the shadow GC as well.
  1312.  *    Should not be used for the CopyGCSource since we like to copy from
  1313.  *    the real GC to the shadow using CopyGC...
  1314.  *
  1315.  * Results:
  1316.  *    None.
  1317.  *
  1318.  * Side Effects:
  1319.  *    Any changes in the real GC are copied to the shadow.
  1320.  *
  1321.  *-----------------------------------------------------------------------
  1322.  */
  1323. /*ARGSUSED*/
  1324. void
  1325. spriteCopyGC (pGCDst, pGCI, changes, pGCSrc)
  1326.     GCPtr         pGCDst;
  1327.     GCInterestPtr pGCI;
  1328.     int          changes;
  1329.     GCPtr         pGCSrc;
  1330. {
  1331.     CopyGC (pGCDst, (GCPtr) pGCDst->devPriv, pGCDst->stateChanges|changes);
  1332. }
  1333.  
  1334.  
  1335. /*
  1336.  * Array of functions to replace the functions in the GC.
  1337.  * Caveat: Depends on the ordering of functions in the GC structure.
  1338.  */
  1339. static void (* spriteGCFuncs[]) () = {
  1340.     spriteFillSpans,
  1341.     spriteSetSpans,
  1342.  
  1343.     spritePutImage,
  1344.     spriteCopyArea,
  1345.     spriteCopyPlane,
  1346.     spritePolyPoint,
  1347.     spritePolylines,
  1348.     spritePolySegment,
  1349.     spritePolyRectangle,
  1350.     spritePolyArc,
  1351.     spriteFillPolygon,
  1352.     spritePolyFillRect,
  1353.     spritePolyFillArc,
  1354.     (void(*)())spritePolyText8,
  1355.     (void(*)())spritePolyText16,
  1356.     spriteImageText8,
  1357.     spriteImageText16,
  1358.     spriteImageGlyphBlt,
  1359.     spritePolyGlyphBlt,
  1360.     spritePushPixels,
  1361.     spriteLineHelper,
  1362.     spriteChangeClip,
  1363.     spriteDestroyClip,
  1364.     spriteCopyClip,
  1365. };
  1366.  
  1367. /*-
  1368.  *-----------------------------------------------------------------------
  1369.  * spriteCreatePrivGC --
  1370.  *    Create a GC private to the Sun DDX code. Such a GC is unhampered
  1371.  *    by any shadow GC and should only be used by functions which know
  1372.  *    what they are doing. This substitutes the old CreateGC function
  1373.  *    in the drawable's screen's vector and calls the DIX CreateGC
  1374.  *    function. Once done, it restores the CreateGC vector to its
  1375.  *    proper state and returns the GCPtr CreateGC gave back.
  1376.  *
  1377.  * Results:
  1378.  *    A pointer to the new GC.
  1379.  *
  1380.  * Side Effects:
  1381.  *    The GC's graphicsExposures field is set FALSE.
  1382.  *
  1383.  *-----------------------------------------------------------------------
  1384.  */
  1385. GCPtr
  1386. spriteCreatePrivGC(pDrawable, mask, pval, pStatus)
  1387.     DrawablePtr      pDrawable;
  1388.     BITS32      mask;
  1389.     long      *pval;
  1390.     BITS32      *pStatus;
  1391. {
  1392.     fbFd          *fb;
  1393.     GCPtr         pGC;
  1394.     BITS32        ge = FALSE;
  1395.  
  1396.     fb = &spriteFbs[pDrawable->pScreen->myNum];
  1397.     pDrawable->pScreen->CreateGC = fb->CreateGC;
  1398.  
  1399.     pGC = GetScratchGC (pDrawable->depth, pDrawable->pScreen);
  1400.     ChangeGC (pGC, mask, pval);
  1401.     ChangeGC (pGC, GCGraphicsExposures, &ge);
  1402.  
  1403.     pDrawable->pScreen->CreateGC = spriteCreateGC;
  1404.  
  1405.     return pGC;
  1406. }
  1407.  
  1408. /*-
  1409.  *-----------------------------------------------------------------------
  1410.  * spriteCreateGC --
  1411.  *    This function is used to get our own validation hooks into each
  1412.  *    GC to preserve the cursor. It calls the regular creation routine
  1413.  *    for the screen and then, if that was successful, tacks another
  1414.  *    GCInterest structure onto the GC *after* the one placed on by
  1415.  *    the screen-specific CreateGC...
  1416.  *
  1417.  * Results:
  1418.  *    TRUE if created ok. FALSE otherwise.
  1419.  *
  1420.  * Side Effects:
  1421.  *    A GCInterest structure is stuck on the end of the GC's list.
  1422.  *
  1423.  *-----------------------------------------------------------------------
  1424.  */
  1425. Bool
  1426. spriteCreateGC (pGC)
  1427.     GCPtr    pGC;    /* The GC to play with */
  1428. {
  1429.     GCInterestPtr    pGCI;
  1430.     register GCPtr    pShadowGC;
  1431.     int            i;
  1432.     
  1433.     if ((*spriteFbs[pGC->pScreen->myNum].CreateGC) (pGC)) {
  1434.     
  1435.     if (pGC->depth != pGC->pScreen->rootDepth) {
  1436.         /*
  1437.          * This GC will never be used for drawing on the screen so no
  1438.          * shadow needed.
  1439.          */
  1440.         return (TRUE);
  1441.     }
  1442.     pShadowGC = (GCPtr) Xalloc (sizeof (GC));
  1443.     if (pShadowGC == (GCPtr)NULL) {
  1444.         return FALSE;
  1445.     }
  1446.     
  1447.     *pShadowGC = *pGC;
  1448.     pGC->devPriv = (pointer)pShadowGC;
  1449.     bcopy (spriteGCFuncs, &pGC->FillSpans, sizeof (spriteGCFuncs));
  1450.     
  1451.     pGCI = (GCInterestPtr) Xalloc (sizeof (GCInterestRec));
  1452.     if (!pGCI) {
  1453.         return FALSE;
  1454.     }
  1455.  
  1456.     /*
  1457.      * Any structure being shared between these two GCs must have its
  1458.      * reference count incremented. This includes:
  1459.      *  font, tile, stipple.
  1460.      * Anything which doesn't have a reference count must be duplicated:
  1461.      *  dash
  1462.      * 
  1463.      */
  1464.     if (pGC->font) {
  1465.         pGC->font->refcnt++;
  1466.     }
  1467.     if (pGC->tile) {
  1468.         pGC->tile->refcnt++;
  1469.     }
  1470.     if (pGC->stipple) {
  1471.         pGC->stipple->refcnt++;
  1472.     }
  1473.  
  1474.     pShadowGC->dash = (unsigned char *)
  1475.         Xalloc(pGC->numInDashList * sizeof(unsigned char));
  1476.     for (i=0; i<pGC->numInDashList; i++) {
  1477.         pShadowGC->dash[i] = pGC->dash[i];
  1478.     }
  1479.  
  1480.     pGC->pNextGCInterest = pGCI;
  1481.     pGC->pLastGCInterest = pGCI;
  1482.     pGCI->pNextGCInterest = (GCInterestPtr) &pGC->pNextGCInterest;
  1483.     pGCI->pLastGCInterest = (GCInterestPtr) &pGC->pNextGCInterest;
  1484.     pGCI->length = sizeof(GCInterestRec);
  1485.     pGCI->owner = 0;                /* server owns this */
  1486.     pGCI->ValInterestMask = ~0;         /* interested in everything */
  1487.     pGCI->ValidateGC = spriteValidateGC;
  1488.     pGCI->ChangeInterestMask = 0;         /* interested in nothing */
  1489.     pGCI->ChangeGC = (int (*)()) NULL;
  1490.     pGCI->CopyGCSource = (void (*)())NULL;
  1491.     pGCI->CopyGCDest = spriteCopyGC;
  1492.     pGCI->DestroyGC = spriteDestroyGC;
  1493.     
  1494.  
  1495.     /*
  1496.      * Because of this weird way of handling the GCInterest lists,
  1497.      * we need to modify the output library's GCInterest structure to
  1498.      * point to the pNextGCInterest field of the shadow GC...
  1499.      */
  1500.     pGCI = pShadowGC->pNextGCInterest;
  1501.     pGCI->pLastGCInterest = pGCI->pNextGCInterest =
  1502.         (GCInterestPtr) &pShadowGC->pNextGCInterest;
  1503.  
  1504.     return TRUE;
  1505.     } else {
  1506.     return FALSE;
  1507.     }
  1508. }
  1509.